Skip to content

Conversation

@dxnter
Copy link
Contributor

@dxnter dxnter commented Jan 5, 2026

Fixes #56902

Problem

When cloning a database connection and setting a different table prefix, the prefix is not applied correctly.

$original = DB::connection('mysql');
$cloned = clone $original;
$cloned->setTablePrefix('foo_');

// Laravel 11.x - appeared to work, but affected BOTH connections
$cloned->table('contacts')->get();  // Queries: foo_contacts
$original->table('contacts')->get(); // Also queries: foo_contacts (not intentional)

// Laravel 12.x - broken, prefix ignored entirely
$cloned->table('contacts')->get();  // Queries: contacts (prefix ignored)
$original->table('contacts')->get(); // Queries: contacts

Root Cause

c78fa3d refactored how grammars access table prefixes. Previously, grammars stored their own $tablePrefix property. Now they dynamically retrieve it from their connection reference.

Laravel 11 behavior (before c78fa3d):

// Connection.php
public function setTablePrefix($prefix)
{
    $this->tablePrefix = $prefix;
    $this->getQueryGrammar()->setTablePrefix($prefix); // grammar also updated
    return $this;
}

// Grammar.php
protected $tablePrefix = '';

public function wrapTable($table) {
    return $this->wrapValue($this->tablePrefix . $table);
}

When cloning, the grammar object was shallow-copied. Calling setTablePrefix() on the clone updated the shared grammar, affecting both connections.

Laravel 12 behavior (after c78fa3d):

// Connection.php
public function setTablePrefix($prefix)
{
    $this->tablePrefix = $prefix;
    // Grammar is no longer updated and read dynamically
    return $this;
}

// Grammar.php
public function wrapTable($table) {
    $prefix = $this->connection->getTablePrefix();  // reads from connection
    return $this->wrapValue($prefix . $table);
}

When cloning, the grammar's $connection reference still points to the original connection. Calling setTablePrefix() on the clone only updates the clone's prefix, but the grammar still reads from the original connection, ignoring the new prefix.

Solution

Added __clone() to the Connection class to re-initialize grammars with the cloned connection.

@dxnter
Copy link
Contributor Author

dxnter commented Jan 6, 2026

@hafezdivandari Thanks for taking a look at this! Naturally, you're most familiar with the changes in #54487 😅

Those seemed like the only method calls necessary when cloning, but let me know if I'm forgetting anything

@hafezdivandari
Copy link
Contributor

hafezdivandari commented Jan 6, 2026

The $queryGrammar and $schemaGrammar properties must be re-initialized when cloning the Connection, because the connection instance ($this) is injected into these classes:

protected function getDefaultQueryGrammar()
{
return new QueryGrammar($this);
}

public function useDefaultSchemaGrammar()
{
$this->schemaGrammar = $this->getDefaultSchemaGrammar();
}

In contrast, $this is not injected into the Processor:

return new Processor;

Therefore, I think calling $this->useDefaultPostProcessor() in __clone appears to be redundant (the original and cloned connections can share the same processor instance). You may check if the tests are passing without this line.

For reference, the main issue also exists in the 11.x branch. When cloning a connection, the grammar instances continue to reference the original connection rather than the cloned one. As a result, my PR targeting 12.x did not introduce a new bug, but rather exposed an existing one!

@dxnter
Copy link
Contributor Author

dxnter commented Jan 6, 2026

@hafezdivandari Thanks for the insight, I went ahead and removed $this->useDefaultPostProcessor().

That's an interesting point you raised about your PR exposing an existing bug. The issue was reported as a regression, but as you noted, it also existed in a different capacity in 11.x. Users likely didn't notice because the unintended side effect (shared grammar affecting both connections) happened to make their cloned connection work correctly, even though it incorrectly modified the original connection.

I've updated the PR description to better reflect what's going on here.

@taylorotwell taylorotwell merged commit b95b530 into laravel:12.x Jan 7, 2026
70 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Table prefix no longer working in Laravel 12

3 participants